﻿using System;
using HK.Core.Common;
using HK.Core.Common.Data;
using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.GUIEx.Attribute;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Core.Serializable.Attribute;
using HK.Core.Serializable.Data;
using HK.Core.Settings.Protocol;
using UnityEngine;
using UnityEngine.Serialization;

namespace HK.Core.Settings.Data
{
    /// <summary>
    /// 加载缓存池大小设定数据
    /// </summary>
    [Serializable]
    public sealed class LoadPoolSizeSettings : JsonData<LoadPoolSizeSettings>, ILoadPoolSizeSettings
    {

#region Create

        /// <summary>
        /// 创建缓存池大小设定数据
        /// </summary>
        /// <returns>缓存池大小设定数据</returns>
        public static LoadPoolSizeSettings Create()
        {
            return new LoadPoolSizeSettings();
        }

#endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private LoadPoolSizeSettings() {}
        
        [SerializeField, IntSlideMinMax("Ab个数", 50, 900)]
        private int abNum = 50;
        /// <summary>
        /// Ab数量
        /// </summary>
        public int AbNum 
        {
            get => abNum;
            private set => abNum = value;
        }
        
        [SerializeField, IntSlideMinMax("文本资产", 50, 900, "即：TextAsset类型对象")]
        private int textNum = 50;
        /// <summary>
        /// 文本资产数量
        /// <para>* 即 : TextAsset</para>
        /// </summary>
        public int TextNum
        {
            get => textNum;
            private set => textNum = value;
        }
        
        [SerializeField, IntSlideMinMax("可序列化对象", 50, 900, "既：ScriptableObject类型对象")]
        private int sObjectNum = 50;
        /// <summary>
        /// 可序列化对象缓存池数量
        /// </summary>
        public int SObjectNum 
        {
            get => sObjectNum;
            private set => sObjectNum = value;
        }
        
        [SerializeField, IntSlideMinMax("预制体", 50, 900)]
        private int prefabNum = 50;
        /// <summary>
        /// 预制体
        /// </summary>
        public int PrefabNum 
        {
            get => prefabNum;
            private set => prefabNum = value;
        }
        
        [SerializeField, IntSlideMinMax("Sprite", 50, 900)]
        private int spriteNum = 50;
        /// <summary>
        /// Sprite数量
        /// </summary>
        public int SpriteNum 
        {
            get => spriteNum;
            private set => spriteNum = value;
        }

        [SerializeField, IntSlideMinMax("图集", 50, 900)]
        private int atlasNum = 50;
        /// <summary>
        /// 图集数量
        /// </summary>
        public int AtlasNum 
        {
            get => atlasNum;
            private set => atlasNum = value;
        }
        
        [SerializeField, IntSlideMinMax("纹理", 50, 900)]
        private int texNum = 50;
        /// <summary>
        /// 纹理数量
        /// </summary>
        public int TexNum 
        {
            get => texNum;
            private set => texNum = value;
        }

        [SerializeField, IntSlideMinMax("材质", 50, 900)]
        private int matNum = 50;
        /// <summary>
        /// 材质数量
        /// </summary>
        public int MatNum 
        {
            get => matNum;
            private set => matNum = value;
        }

        [SerializeField, IntSlideMinMax("Shader", 50, 900)]
        private int shaderNum = 50;
        /// <summary>
        /// Shader数量
        /// </summary>
        public int ShaderNum 
        {
            get => shaderNum;
            private set => shaderNum = value;
        }

        [SerializeField, IntSlideMinMax("网格", 50, 900)]
        private int meshNum = 50;
        /// <summary>
        /// 网格数量
        /// </summary>
        public int MeshNum 
        {
            get => meshNum;
            private set => meshNum = value;
        }

        /// <summary>
        /// 应用数据
        /// </summary>
        /// <param name="iData">数据</param>
        /// <param name="iImport">导入标志位(true:从相应的*.json文件导入; false:反之;)</param>
        /// <returns>true:有变更; false:无变更;</returns>
        public override bool ApplyData(IJsonData iData, bool iImport = false)
        {
            if (null == iData || !iData.Valid) return false;
            var dirty = base.ApplyData(iData, iImport);
            if (dirty && !iImport)
            {
                Dirty = true;
            }

            if (iData is ILoadPoolSizeSettings settings)
            {
                abNum = UpdateValue(abNum, settings.AbNum, iImport);
                textNum = UpdateValue(textNum, settings.TextNum, iImport);
                sObjectNum = UpdateValue(sObjectNum, settings.SObjectNum, iImport);
                prefabNum = UpdateValue(prefabNum, settings.PrefabNum, iImport);
                spriteNum = UpdateValue(spriteNum, settings.SpriteNum, iImport);
                atlasNum = UpdateValue(atlasNum, settings.AtlasNum, iImport);
                texNum = UpdateValue(texNum, settings.TexNum, iImport);
                matNum = UpdateValue(matNum, settings.MatNum, iImport);
                shaderNum = UpdateValue(shaderNum, settings.ShaderNum, iImport);
                meshNum = UpdateValue(meshNum, settings.MeshNum, iImport);
            }
            
            return Dirty;
        }

        /// <summary>
        /// 清空
        /// </summary>
        public override void Clear()
        {
            base.Clear();

            abNum = 50;
            textNum = 50;
            sObjectNum = 50;
            prefabNum = 50;
            spriteNum = 50;
            atlasNum = 50;
            texNum = 50;
            matNum = 50;
            shaderNum = 50;
            meshNum = 50;
        }
    }
    
    /// <summary>
    /// 游戏设定数据
    /// </summary>
    [Serializable]
    public class GameSettingsData : SAssetData, IGameSettingsData
    {
        [SerializeField, GenericField("游戏名", null, "App安装后，手机桌面显示的名字。")]
        private string gameName = null;

        /// <summary>
        /// 游戏名
        /// </summary>
        public string GameName
        {
            get => gameName;
            private set => gameName = value;
        }
        
        [SerializeField, GenericField("打包Id", null, "包体Id。例如：com.xxx.yyy")]
        private string buildId = null;
        /// <summary>
        /// 打包Id
        /// </summary>
        public string BuildId 
        {
            get => buildId;
            private set => buildId = value;
        }
        
        [SerializeField, GenericField("Debug", null, "测试版本:true")]
        private bool isDebug = false;
        /// <summary>
        /// Debug标志位
        /// </summary>
        public bool IsDebug 
        {
            get => isDebug;
            private set => isDebug = value;
        }
        
        [SerializeField, GenericField("加密", null, "勾选，则Ab，Lua等都将被加密")]
        private bool encryption = false;
        /// <summary>
        /// 加密标志位
        /// </summary>
        public bool Encryption 
        {
            get => encryption;
            internal set => encryption = value;
        }
        
        [SerializeField, GenericField("平台/渠道")]
        private PlatformType platform = PlatformType.Android;
        /// <summary>
        /// Debug标志位
        /// </summary>
        public PlatformType Platform 
        {
            get => platform;
            private set => platform = value;
        }
        
#region Pool

        [SerializeField, GroupView("缓存池大小设定")]
        private LoadPoolSizeSettings loadPoolSize = LoadPoolSizeSettings.Create();
        /// <summary>
        /// 缓存池大小设定数据
        /// </summary>
        public ILoadPoolSizeSettings LoadPoolSize => loadPoolSize;

#endregion

#region Download

        [SerializeField, GroupView("下载设定")]
        private DownloadSettingsData download = DownloadSettingsData.Create();
        /// <summary>
        /// 下载设定
        /// </summary>
        public IDownloadSettingsData Download => download;
        
        /// <summary>
        /// 下载完成标志位
        /// </summary>
        public bool Downloaded 
        {
            get => download.Downloaded;
            private set => download.Downloaded = value;
        }

        /// <summary>
        /// 标记下载完成
        /// <para> * 下载完成，重置该标志位</para>
        /// </summary>
        public void MarkAsDownloaded() => Downloaded = true;

        /// <summary>
        /// 撤销标记 - 下载完成
        /// <para> * 重新开始下载前，重置该状态位</para>
        /// </summary>
        public void UnMarkAsDownloaded() => Downloaded = false;

#endregion
        
#region Servers

        [SerializeField, ListView("服务器设定", "serverId", (int)GUIOperateOptions.ServersView, 10)]
        private ServersSettingsData servers = ServersSettingsData.Create();
        /// <summary>
        /// 服务器列表
        /// </summary>
        public IServersSettingsData Servers => servers;

#endregion
        
        /// <summary>
        /// 应用数据
        /// </summary>
        /// <param name="iData">数据</param>
        /// <param name="iImport">导入标志位(true:从相应的*.json文件导入; false:反之;)</param>
        /// <returns>true:有变更; false:无变更;</returns>
        public override bool ApplyData(IJsonData iData, bool iImport = false)
        {
            if (null == iData || !iData.Valid) return false;
            var dirty = base.ApplyData(iData, iImport);
            if (dirty && !iImport)
            {
                Dirty = true;
            }

            if (iData is IGameSettingsData gameData)
            {
                gameName = UpdateValue(gameName, gameData.GameName, iImport);
                buildId = UpdateValue(buildId, gameData.BuildId, iImport);
                isDebug = UpdateValue(isDebug, gameData.IsDebug, iImport);
                encryption = UpdateValue(encryption, gameData.Encryption, iImport);
                
                dirty = loadPoolSize.ApplyData(gameData.LoadPoolSize);
                if (dirty && !iImport)
                {
                    Dirty = true;
                }
                
                dirty = download.ApplyData(gameData.Download);
                if (dirty && !iImport)
                {
                    Dirty = true;
                }

                dirty = servers.ApplyData(gameData.Servers);
                if (dirty && !iImport)
                {
                    Dirty = true;
                }
            }

            return Dirty;
        }

        /// <summary>
        /// 清空
        /// </summary>
        public override void Clear()
        {
            base.Clear();

            gameName = null;
            buildId = null;
            isDebug = false;
            encryption = false;
            
            loadPoolSize.Clear();
            download.Clear();
            servers.Clear();
        }
    }
}
